<?php
namespace app\api\services;

use app\api\cache\KeysUtil;
use app\api\cache\Marketing;
use app\api\cache\RedisCache;
use app\api\consDir\CommunityConst;
use app\common\libs\Singleton;
use app\common\models\Community\Community;
use app\common\models\Community\CommunityOrder;
use app\common\models\Community\CommunityUser;
use app\common\models\Member\Member;
use app\common\models\Member\MemberServiceUpgradeLog;
use app\common\models\Order\OrderPay;
use app\common\models\Packs\Packs;
use app\common\models\Packs\PacksBusinessUser;
use app\common\models\Packs\PacksConfig;
use app\common\models\Packs\PacksOrder;
use app\common\models\Packs\PacksOrderExpress;
use app\common\models\Packs\PacksOrderProducts;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;

class PacksService
{
    use Singleton;

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getPacksInfo($packsId): array
    {
        $whereArr                = ['id' => $packsId];
        $packsInfos              = Packs::getInstance()->where($whereArr)->find();
        $packsInfos['realPrice'] = $packsInfos['discount'] > 0 ? bcmul($packsInfos['salesPrice'], bcmul($packsInfos['discount'], 0.01, 2), 2) : $packsInfos['salesPrice'];
        return empty($packsInfos) ? [] : $packsInfos->toArray();
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getPacksList($name, $page, $pageSize): array
    {
        $where = [
            ['deleted', '=', 0],
            ['status', '=', 1],
        ];
        if ( ! empty($name)) {
            $where[] = ['packs_name', 'like', '%' . $name . '%'];
        }
        $list = Packs::getInstance()
            ->where($where)
            ->page($page, $pageSize)
            ->order('sort desc,id desc')
            ->select();
        foreach ($list as &$v) {
            $v['realPrice'] = $v['discount'] > 0 ? bcmul($v['salesPrice'], bcmul($v['discount'], 0.01, 2), 2) : $v['salesPrice'];
        }
        return empty($list) ? [] : $list->toArray();
    }

    public function getPacksContent($type, $getPacksInfo)
    {
        $data = ['trval' => 'travelContent', 'products' => 'productsContent'];
        return is_string($getPacksInfo[$data[$type]]) ? json_decode($getPacksInfo[$data[$type]], true) : [];
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function getPacksOrderInfo($orderId): array
    {
        $whereArr   = ['id' => $orderId];
        $packsOrder = PacksOrder::getInstance()->where($whereArr)->find();
        if ($packsOrder) {
            $packsOrder['express']  = PacksOrderExpress::getInstance()->where('order_no', $packsOrder['orderNo'])->find() ?? [];
            $packsOrder['products'] = PacksOrderProducts::getInstance()->where('order_no', $packsOrder['orderNo'])->select() ?? [];
            $packsOrder['packs']    = $this->getPacksInfo($packsOrder['packsId']);
            $packsOrder['tel']      = $this->getPacksConfig('tel');
        }
        return empty($packsOrder) ? [] : $packsOrder->toArray();
    }

    public function payPacksOrder($orderInfo, $payPrice, $amountPrice, $type)
    {
        $payNo = getNo('PAPAY');
        $data  = [
            'pay_status'   => $type,
            'pay_price'    => $payPrice,
            'user_id'      => $orderInfo['memberId'],
            'order_no'     => $orderInfo['orderNo'],
            'pay_no'       => $payNo,
            'pay_amount'   => $amountPrice,
            'order_status' => 3,
            'expire_at'    => date('Y-m-d H:i:s', strtotime('+15 minute')),
        ];
        $payId = OrderPay::getInstance()->insertGetId($data);
        if ( ! $payId) {
            return false;
        }
        return $data;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function payCallback($orderNo): bool
    {
        $payInfo = OrderPay::getInstance()->where('order_no', $orderNo)->find();
        if (empty($payInfo)) {
            return false;
        }

        $packsOrder = PacksOrder::getInstance()->where('order_no', $orderNo)->find();
        if (empty($packsOrder)) {
            return false;
        }

        try {
            $orderData = [
                'status'   => 1,
                'pay_type' => $payInfo['payStatus'],
                'pay_at'   => date('Y-m-d H:i:s'),
            ];

            //更新礼包订单
            PacksOrder::getInstance()->where('order_no', $orderNo)->update($orderData);

            //扣除余额
            if ($payInfo['pay_amount'] > 0) {
                $msg = '购买礼包抵扣，抵扣订单' . $orderNo;
                MemberService::getInstance()->addFinanceLog($payInfo['userId'], 'pay_packs', $payInfo['payAmount'], 1, $msg, $payInfo['orderNo']);
            }
        } catch (\Exception $e) {
            Log::info($e->getMessage());
            return false;
        }
        return true;
    }

    /**
     * 礼包分佣
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function dividend($orderNo): bool
    {
        $packsOrder = PacksOrder::getInstance()->where('order_no', $orderNo)->find();
        if (empty($packsOrder)) {
            return false;
        }
        $member = Member::getInstance()->where('id', $packsOrder['memberId'])->find();
        if (empty($member)) {
            return false;
        }

        $direct = Member::getInstance()->where('id', $member['inviteId'])->find();
        //直推收益
        if ($direct) {
            $rate  = $this->getPacksConfig('direct_earnings');
            $msg   = '推广礼包，获得直推收益，收益比例' . $rate . '%，礼包订单' . $orderNo;
            $price = $this->compute($packsOrder['realPrice'], $rate);
            if ($price > 0) {
                MemberService::getInstance()->addFinanceLog($direct['id'], 'vip_earnings', $price, 5, $msg, $orderNo, 1, 1);
            }
        }

        //社区经营者收益
        $community = Community::getInstance()->where('comm_id', $member['commId'])->find();
        $where     = [
            ['community_id', '=', $community['id']],
            ['community_status', 'in', [CommunityConst::CHECK_STATUS, CommunityConst::PERMANENT_STATUS]],
        ];
        $communityUser = CommunityUser::getInstance()->where($where)->find();
        if ($communityUser) {
            $rate  = $this->getPacksConfig('community_op_earnings');
            $msg   = '推广礼包，获得社区经营者收益，收益比例' . $rate . '%，礼包订单' . $orderNo;
            $price = $this->compute($packsOrder['realPrice'], $rate);
            if ($price > 0) {
                MemberService::getInstance()->addFinanceLog($communityUser['userId'], 'community_op_earnings', $price, 5, $msg, $orderNo, 1, 1);
            }
        }

        //服务商收益
        $partnerInfo = MemberService::getInstance()->getMyPartnerInfo($packsOrder['memberId']);
        if ($partnerInfo) {
            //直推人和服务商同一人，不发放服务商收益
            if ($direct && $direct['id'] != $partnerInfo['partnerId']) {
                $rate  = $this->getPacksConfig('service_earnings');
                $msg   = '推广礼包，获得服务商收益，收益比例' . $rate . '%，礼包订单' . $orderNo;
                $price = $this->compute($packsOrder['realPrice'], $rate);
                MemberService::getInstance()->addFinanceLog($partnerInfo['partnerId'], 'service_earnings', $price, 5, $msg, $orderNo, 1, 1);
            }
        }

        //平级服务商
        $myPartner = MemberService::getInstance()->getMyPartner($member);
        if ($myPartner) {
            $rate  = $this->getPacksConfig('ping_service_earnings');
            $price = $this->compute($packsOrder['realPrice'], $rate);
            $msg   = '推广礼包，获得平级服务商收益，收益比例' . $rate . '%，礼包订单' . $orderNo;
            MemberService::getInstance()->addFinanceLog($myPartner['id'], 'ping_service_earnings', $price, 5, $msg, $orderNo,1,1);
        }

        //获取用户的省市区代 极差
        $partnerInfo = MemberService::getInstance()->getMyAgencyPacksInfo($packsOrder['memberId']);
        if ($partnerInfo['provinceUid'] > 0) {
            //$provinceEarnings = $partnerInfo['provinceEarnings'];
            $provinceEarnings = $this->getPacksConfig('province_earnings');
            $msg              = "推广礼包，获得区域（" . $partnerInfo['provinceName'] . "）会员收益，收益比例" . $provinceEarnings . '%，礼包订单' . $orderNo;
            $price            = $this->compute($packsOrder['realPrice'], $provinceEarnings);
            MemberService::getInstance()->addFinanceLog($partnerInfo['provinceUid'], 'province_earnings', $price, 5, $msg, $orderNo, 1, 1);
        }
        if ($partnerInfo['cityUid'] > 0) {
            //$cityEarnings = $partnerInfo['cityEarnings'];
            $cityEarnings = $this->getPacksConfig('city_earnings');
            $msg          = "推广礼包，获得区域（" . $partnerInfo['cityName'] . "）会员收益，收益比例" . $cityEarnings . '%，礼包订单' . $orderNo;
            $price        = $this->compute($packsOrder['realPrice'], $cityEarnings);
            MemberService::getInstance()->addFinanceLog($partnerInfo['cityUid'], 'city_earnings', $price, 5, $msg, $orderNo, 1, 1);
        }
        if ($partnerInfo['countryUid'] > 0) {
            //$areaEarnings = $partnerInfo['areaEarnings'];
            $areaEarnings = $this->getPacksConfig('area_earnings');
            $msg          = "推广礼包，获得区域（" . $partnerInfo['countryName'] . "）会员收益，收益比例" . $areaEarnings . '%，礼包订单' . $orderNo;
            $price        = $this->compute($packsOrder['realPrice'], $areaEarnings);
            MemberService::getInstance()->addFinanceLog($partnerInfo['countryUid'], 'area_earnings', $price, 5, $msg, $orderNo, 1, 1);
        }

        //事业部收益
        $list = $this->getBusinessUser();
        if ($list) {
            foreach ($list as $v) {
                $price = $this->compute($packsOrder['realPrice'], $v['incomeRate']);
                if ($price > 0) {
                    $msg = '推广礼包，获得事业部收益，收益比例' . $v['incomeRate'] . '%，礼包订单' . $orderNo;
                    MemberService::getInstance()->addFinanceLog($v['userId'], 'business_earnings', $price, 5, $msg, $orderNo, 1, 1);
                }
            }
        }

        //赠送会员等级 已经是服务商不更新
        if ( ! empty($packsOrder['giveMemberLevel'])) {
            //level 用户等级 0普通会员 1vip会员 2服务商 3代理 4社区经营者
            // 这里不能够修改 level 了，level有专门的升级逻辑处理
            $memberData = [];
            if ($packsOrder['giveMemberLevel'] == 'vip') {
                // $data = ['is_vip' => 1, 'level' => 1];
                $memberData = ['is_vip' => 1];
            } else if ($packsOrder['giveMemberLevel'] == 'partner') {
                // $data = ['is_partner' => 1, 'level' => 2];
                $memberData = ['is_partner' => 1];
            }
            $serviceSet = Marketing::getKeyData('marketing', 'service_set');
            if ( ! empty($memberData)) {
                //升级条件且
                $isUpdate = 0;
                if(!empty($serviceSet) && $serviceSet['up_status'] == 1){
                    $where = [
                        ['status','=',2],
                        ['type','=',3],
                        ['user_id','=',$packsOrder['memberId']]
                    ];
                    $count = CommunityOrder::getInstance()->where($where)->count();
                    if($count > 0){
                       $isUpdate = 1;
                    }
                }else{
                    $isUpdate = 1;
                }
                if($isUpdate){
                    Member::getInstance()->where('id', $packsOrder['memberId'])
                        ->update($memberData);
                    $serviceSet = Marketing::getKeyData('marketing', 'service_set');
                    if(isset($serviceSet['up_status']) && $serviceSet['up_status'] == 1){
                        $remark = $member['phone'].'会员完成社区升级任务购买一个社区和'.$packsOrder['salesPrice'].'礼包，自动升级为服务商';
                    }else{
                        $remark = $member['phone'].'会员完成社区升级任务购买一个'.$packsOrder['salesPrice'].'礼包，自动升级为服务商';
                    }
                    $data = [
                        'user_id' => $packsOrder['memberId'],
                        'order_no' => $orderNo,
                        'remark' => $remark
                    ];
                    MemberServiceUpgradeLog::getInstance()->insert($data);
                }
            }
        }

        //赠送数字积分
        /*if ($packsOrder['giveDigitalCredits'] > 0) {
            $msg = '购买礼包，赠送数字积分';
            MemberService::getInstance()->addFinanceLog($packsOrder['memberId'], 'packs', $packsOrder['giveDigitalCredits'], 6, $msg, $orderNo, 2);
        }*/
        if ($packsOrder['realPrice'] > 0) {
            $msg = '购买礼包，赠送贡献值，订单号' . $orderNo;
            MemberService::getInstance()->addFinanceLog($packsOrder['memberId'], 'packs', $packsOrder['realPrice'], 7, $msg, $orderNo);
        }

        //赠送数字资产
        if ($packsOrder['giveDigitalAssets'] > 0) {
            $msg = '购买礼包，赠送数字资产';
            MemberService::getInstance()->addFinanceLog($packsOrder['memberId'], 'packs', $packsOrder['giveDigitalAssets'], 6, $msg, $orderNo, 1);
        }
        //第一次买礼包赠送贡献值
        $where = [
            ['member_id', '=', $packsOrder['memberId']],
            ['status', 'in', [1, 2, 3]],
        ];
        $count = PacksOrder::getInstance()->where($where)->count();
        if ($count == 1) {
            MemberService::getInstance()->sendNewTaskGxz($packsOrder['memberId'], 'first_packs', '第一次买礼包，赠送贡献值');
        }
        //加入分润池
        MemberService::getInstance()->profitPoolLog($packsOrder['memberId'], $packsOrder['realPrice'], $orderNo, $packsOrder['realPrice'], 5);
        return true;
    }

    /**
     * 计算收益
     * @param $price
     * @param $rate
     * @return string
     */
    public function compute($price, $rate): string
    {
        return bcmul($price, bcmul($rate, 0.01, 4), 4);
    }

    public function getPacksConfig($keys)
    {
        $config = self::getConfigInfo($keys);
        if (empty($config)) {
            $where  = ['key' => $keys];
            $config = PacksConfig::getInstance()->where($where)->find()->toArray();
            if ($config['unit'] == 'json') {
                $config['value'] = json_decode($config['value'], true);
            }
            self::setConfigInfo($keys, $config);
        }
        return $config['value'];
    }

    public static function setConfigInfo($key, $data): bool
    {
        is_array($data) && $data = json_encode($data, true);
        return RedisCache::set(KeysUtil::getPacksConfigKey($key), $data);
    }

    public static function getConfigInfo($key)
    {
        $data = RedisCache::get(KeysUtil::getPacksConfigKey($key));
        return is_array($data) ? $data : json_decode($data, true);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function getBusinessUser(): array
    {
        $where = [
            ['status', '=', 1],
            ['deleted', '=', 0],
        ];
        $list = PacksBusinessUser::getInstance()->where($where)->field('user_id,income_rate')->select();
        return empty($list) ? [] : $list->toArray();
    }

    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function getPacksOrderList($status, $page, $pageSize, $userId): array
    {
        $where = [
            ['deleted', '=', 0],
            ['member_id', '=', $userId],
        ];
        if (is_numeric($status)) {
            $where[] = ['status', '=', $status];
        }
        $list = PacksOrder::getInstance()
            ->where($where)
            ->page($page, $pageSize)
            ->order('id desc')
            ->select();
        foreach ($list as &$v) {
            $v['products'] = PacksOrderProducts::getInstance()->where('order_no', $v['orderNo'])->select() ?? [];
            $v['packs']    = $this->getPacksInfo($v['packsId']);
        }
        return empty($list) ? [] : $list->toArray();
    }

    public function confirm($order): bool
    {
        PacksOrder::getInstance()->startTrans();
        try {
            $data = [
                'status'        => 3, //完成
                'completion_at' => date('Y-m-d H:i:s'),
            ];

            PacksOrder::getInstance()->where('order_no', $order['orderNo'])->update($data);
            //分佣
            if ($order['isUpgrade'] == 0) {
                $this->dividend($order['orderNo']);
                $data = [
                    'is_upgrade'   => 1,
                    'upgrade_time' => date('Y-m-d H:i:s'),
                ];
                PacksOrder::getInstance()->where('id', $order['id'])->update($data);
            }
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            PacksOrder::getInstance()->rollback();
            return false;
        }
        PacksOrder::getInstance()->commit();
        return true;
    }

    public function upgradeService($userId): bool
    {
        $memberData = Member::getInstance()->where('id',$userId)->find();
        $serviceSet = Marketing::getKeyData('marketing', 'service_set');
        if ( ! empty($memberData)) {
            //升级条件且
            $isUpdate = 0;
            if(!empty($serviceSet) && $serviceSet['up_status'] == 1){
                $where = [
                    ['status','in',[1,2,3]],
                    ['member_id','=',$memberData['id']]
                ];
                $count = PacksOrder::getInstance()->where($where)->count();
                if($count > 0){
                    $isUpdate = 1;
                }
            }
            if($isUpdate){
                Member::getInstance()->where('id', $memberData['id'])
                    ->update(['is_partner' => 1]);
                $where = [
                    ['status','in',[1,2,3]],
                    ['member_id','=',$memberData['id']]
                ];
                $packsOrder = PacksOrder::getInstance()->where($where)->order('id desc')->find();
                if(isset($serviceSet['up_status']) && $serviceSet['up_status'] == 1){
                    $remark = $memberData['phone'].'会员完成社区升级任务购买一个社区和'.$packsOrder['salesPrice'].'礼包，自动升级为服务商';
                }else{
                    $remark = $memberData['phone'].'会员完成社区升级任务购买一个'.$packsOrder['salesPrice'].'礼包，自动升级为服务商';
                }
                $data = [
                    'user_id' => $packsOrder['memberId'] ?? 0,
                    'order_no' => $packsOrder['order_no'] ?? '',
                    'remark' => $remark
                ];
                MemberServiceUpgradeLog::getInstance()->insert($data);
                $event["exchange"] = config('rabbitmq.info_queue');
                RabbitMqService::send($event, ['type' => 'member', 'data' => ['id' => $memberData['id']]]);
            }
        }
        return true;
    }

}
